"""
线性回归预测模型

问题描述：
    线性回归是一种用于建立输入变量和输出变量之间线性关系的预测模型。
    它假设因变量Y与自变量X之间存在线性关系：Y = β0 + β1*X1 + β2*X2 + ... + βn*Xn + ε
    其中β0是截距，βi是回归系数，ε是误差项。

算法原理：
    线性回归通过最小二乘法来估计回归系数，使得预测值与实际值之间的平方误差最小。
    目标函数是最小化残差平方和：min Σ(yi - ŷi)²
    
    求解方法：
    1. 正规方程法：β = (X^T * X)^(-1) * X^T * y
    2. 梯度下降法：迭代更新参数直至收敛

核心概念：
    - 回归系数：表示自变量对因变量的影响程度
    - 决定系数(R²)：衡量模型拟合优度的指标
    - 残差分析：检验模型假设的有效性

应用场景：
    线性回归广泛应用于：
    - 销售预测
    - 房价预测
    - 经济指标预测
    - 气象预测
    - 医学诊断

作者：斯黄
日期：2025年3月4日
"""

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error
import pandas as pd

# 生成示例数据：房屋面积vs房价预测
np.random.seed(42)
house_size = np.random.uniform(50, 200, 100)  # 房屋面积 (平方米)
noise = np.random.normal(0, 5000, 100)  # 噪声
house_price = 500 * house_size + 20000 + noise  # 房价 = 500*面积 + 20000 + 噪声

# 数据预处理
X = house_size.reshape(-1, 1)
y = house_price

# 划分训练集和测试集
split_index = int(0.8 * len(X))
X_train, X_test = X[:split_index], X[split_index:]
y_train, y_test = y[:split_index], y[split_index:]

# 创建线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)

# 预测
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

# 计算评估指标
r2_train = r2_score(y_train, y_pred_train)
r2_test = r2_score(y_test, y_pred_test)
mse_train = mean_squared_error(y_train, y_pred_train)
mse_test = mean_squared_error(y_test, y_pred_test)

print(f"模型参数:")
print(f"回归系数 (斜率): {model.coef_[0]:.2f}")
print(f"截距: {model.intercept_:.2f}")
print(f"\n训练集性能:")
print(f"R² 分数: {r2_train:.4f}")
print(f"均方误差: {mse_train:.2f}")
print(f"\n测试集性能:")
print(f"R² 分数: {r2_test:.4f}")
print(f"均方误差: {mse_test:.2f}")

# 可视化
plt.figure(figsize=(12, 5))

# 训练数据和拟合直线
plt.subplot(1, 2, 1)
plt.scatter(X_train, y_train, alpha=0.6, color='blue', label='训练数据')
plt.plot(X_train, y_pred_train, color='red', linewidth=2, label='回归直线')
plt.xlabel('房屋面积 (m²)')
plt.ylabel('房价 (元)')
plt.title('线性回归模型 - 训练集')
plt.legend()
plt.grid(True)

# 测试数据预测效果
plt.subplot(1, 2, 2)
plt.scatter(y_test, y_pred_test, alpha=0.6, color='green')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', linewidth=2)
plt.xlabel('实际房价')
plt.ylabel('预测房价')
plt.title('预测值 vs 实际值')
plt.grid(True)

plt.tight_layout()
plt.show()

# 残差分析
plt.figure(figsize=(12, 5))

# 残差图
plt.subplot(1, 2, 1)
residuals = y_test - y_pred_test
plt.scatter(y_pred_test, residuals, alpha=0.6)
plt.axhline(y=0, color='red', linestyle='--')
plt.xlabel('预测值')
plt.ylabel('残差')
plt.title('残差图')
plt.grid(True)

# 残差直方图
plt.subplot(1, 2, 2)
plt.hist(residuals, bins=10, alpha=0.7, color='skyblue', edgecolor='black')
plt.xlabel('残差')
plt.ylabel('频数')
plt.title('残差分布直方图')
plt.grid(True)

plt.tight_layout()
plt.show()

# 预测新数据
new_house_sizes = np.array([[80], [120], [150]])
predicted_prices = model.predict(new_house_sizes)

print(f"\n新房屋预测:")
for size, price in zip(new_house_sizes.flatten(), predicted_prices):
    print(f"面积 {size}m² 的房屋预测价格: {price:.2f} 元") 